﻿
// FTech_ListBoxExDlg.cpp : implementation file
//

#include "stdafx.h"
#include "FTech_ListBoxEx.h"
#include "FTech_ListBoxExDlg.h"
#include "afxdialogex.h"
#include "ComPortSet.h"
#include "McuUARTCmdManger.h"
#include "MeterUARTCmdManger.h"
#include "TestSeqEditor.h"
#include "LoginDialog.h"
#include "DoubleCheckToRmSeqs.h"
#include <MMSystem.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <locale.h>
#include <string>
#include <thread>
#include "chineseString.h"
#include "CInputSNDlg.h"
//#define debug_step_by_step
//#define debug_no_com
#ifdef debug_no_com
#define METER_WAIT_MAX (100) // 1000 correct
#define MCU_MAX_WAIT (20)   // 200 correct
#else
#define METER_WAIT_MAX (1000) // 1000 correct
#define MCU_MAX_WAIT (200)   // 200 correct
#endif
#ifdef _DEBUG
#define new DEBUG_NEW
#endif


extern int writeToExcel(CString csRec);
using namespace std;
extern int gtest;
int g_nCount=0;

CFTech_ListBoxExDlg::CFTech_ListBoxExDlg(CWnd* pParent /*=NULL*/)
	: CDialogEx(CFTech_ListBoxExDlg::IDD, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
	loop = true;
	isMCUConnected = false;
	isMeterConnected = false;
	selfTestCmdVec.clear();
	ifStopWhenError = -1;
	ifRevertPort = -1;
	totalSecondCount = 0;
	workingGroup = -1;
	workingName = L"";
	ifFix2SecondBeforeReadMeter = false;
	testSeqProjectName = L"";
	pRecordDB = nullptr;
	isMcuComError = false;
	isMeterComError = false;
	curSN = "";
	isSelfTesting = false;
	isUserTerminal = false;
	isRequestToStop = false;
	isComTryTimeOut = false;
	tryMeasureTimes = 10;
	interValTime = 100;
	stableRange = 0.01;
}

void CFTech_ListBoxExDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_LIST1, m_lbTest);
	DDX_Control(pDX, IDC_BUTTON3, m_MCUConnectButton);
	DDX_Control(pDX, IDC_BUTTON_DISCON_MCU, m_MCUDisConnectButton);
	DDX_Control(pDX, IDC_BUTTON_CON_METER, m_MeterConnectButton);
	DDX_Control(pDX, IDC_BUTTON_DISCON_METER, m_MeterDisConnectButton);
	DDX_Control(pDX, IDC_EDIT_MEASURE_VAL, mMeasureVal);
	DDX_Control(pDX, IDC_EDIT_curSN, mEditCurSN);
	DDX_Control(pDX, IDC_EDIT_projectName, mEditCurProjectName);
	DDX_Control(pDX, IDC_EDIT_testResult, mTestResult);
	DDX_Control(pDX, IDC_BtnAdd, mAddSeqBtnCtl);
	DDX_Control(pDX, IDC_BtnDelSeq, mDelSeqBtnCtl);
	DDX_Control(pDX, IDC_Btn_INPORT_SEQS, mImportSeqBtnCtl);
	DDX_Control(pDX, IDC_BtnOutputSeq, mOutputSeqBtnCtl);
	DDX_Control(pDX, IDC_PROGRESS1, mProcessPercent);
	DDX_Control(pDX, IDC_BUTTEN_EXECUTE_ALL, mExecuteSeqBtnCtl);
	DDX_Control(pDX, IDC_BUTTON_ENCRIP, mEncryBtnCtl);
	DDX_Control(pDX, IDC_BUTTON_DEENCRY, mDeEncryBtnCtl);
	DDX_Control(pDX, IDC_BUTTON_SELF_TEST, mBtnSelfTest);
	DDX_Control(pDX, IDC_CHECK_IF_STOPWHEN_ERROR, mIfStopWhenError);
	DDX_Control(pDX, IDC_BUTTON_REPORT, mReportBtn);
	DDX_Control(pDX, IDC_EDIT_workingName, mWorkingName);
	DDX_Control(pDX, IDC_EDIT_workingGroup, mWorkingGroup);
	DDX_Control(pDX, IDC_COM_MCU_INMAIN, mMCUComPort);
	DDX_Control(pDX, IDC_COM_METER_INMAIN, mMeterComPort);
	DDX_Control(pDX, IDC_CHECK_REVERS, mReverse);
	DDX_Control(pDX, IDC_ClearSeqButton, mClearSeqButCtl);
	DDX_Control(pDX, IDC_BUTTON_SHOW_MEASURE, mShowMeasureButCtl);
	DDX_Control(pDX, IDC_BUT_CREATE_CSV_DEMO, mCreateDemoCsvBut);
}

BEGIN_MESSAGE_MAP(CFTech_ListBoxExDlg, CDialogEx)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BtnAdd, &CFTech_ListBoxExDlg::OnBnClickedBtnadd)
	ON_BN_CLICKED(IDCANCEL, &CFTech_ListBoxExDlg::OnBnClickedCancel)
	ON_WM_DESTROY()
	ON_CONTROL(LBN_DBLCLK,IDC_LIST1,&CFTech_ListBoxExDlg::OnClickedListBox)
	ON_BN_CLICKED(IDC_BUTTON_CON_MCU, &CFTech_ListBoxExDlg::OnBnClickedMCUPortConnect)
	ON_BN_CLICKED(IDC_BUTTON_DISCON_MCU, &CFTech_ListBoxExDlg::OnBnClickedButtonDisconMcu)
	//ON_BN_CLICKED(IDC_BUTTON_MCU_COM_SET, &CFTech_ListBoxExDlg::OnBnClickedButtonMcuComSet)
	ON_BN_CLICKED(IDC_BUTTEN_EXECUTE_ALL, &CFTech_ListBoxExDlg::OnBnClickedButtenExecuteAll)
	//ON_BN_CLICKED(IDC_BUTTON_METER_COM_SET, &CFTech_ListBoxExDlg::OnBnClickedButtonMeterComSet)
	ON_BN_CLICKED(IDC_BUTTON_CON_METER, &CFTech_ListBoxExDlg::OnBnClickedButtonConMeter)
	ON_BN_CLICKED(IDC_BUTTON_DISCON_METER, &CFTech_ListBoxExDlg::OnBnClickedButtonDisconMeter)
	ON_BN_CLICKED(IDC_BtnDelSeq, &CFTech_ListBoxExDlg::OnBnClickedBtndelseq)
	ON_BN_CLICKED(IDC_BUTTON_SHOW_MEASURE, &CFTech_ListBoxExDlg::OnBnClickedButtonShowMeasure)
	ON_BN_CLICKED(IDC_Btn_INPORT_SEQS, &CFTech_ListBoxExDlg::OnBnClickedBtnInportSeqs)
	ON_WM_TIMER()
	ON_BN_CLICKED(IDC_BtnOutputSeq, &CFTech_ListBoxExDlg::OnBnClickedBtnoutputseq)
	ON_BN_CLICKED(IDC_BUTTON_REPORT, &CFTech_ListBoxExDlg::OnBnClickedButtonReport)
	ON_BN_CLICKED(IDC_BUTTON_SELF_TEST, &CFTech_ListBoxExDlg::OnBnClickedButtonSelfTest)
	ON_BN_CLICKED(IDC_CHECK2, &CFTech_ListBoxExDlg::OnBnClickedCheck2)
	ON_LBN_SELCHANGE(IDC_LIST1, &CFTech_ListBoxExDlg::OnLbnSelchangeList1)
	ON_BN_CLICKED(IDC_BUTTON_ENCRIP, &CFTech_ListBoxExDlg::OnBnClickedButtonEncrip)
	ON_BN_CLICKED(IDC_BUTTON_DEENCRY, &CFTech_ListBoxExDlg::OnBnClickedButtonDeencry)
	ON_BN_CLICKED(IDC_ClearSeqButton, &CFTech_ListBoxExDlg::OnBnClickedClearseqbutton)
	ON_BN_CLICKED(IDC_BUT_CREATE_CSV_DEMO, &CFTech_ListBoxExDlg::OnBnClickedButCreateCsvDemo)
	ON_BN_CLICKED(IDC_UserTerminate, &CFTech_ListBoxExDlg::OnBnClickedUserterminate)
END_MESSAGE_MAP()


// CFTech_ListBoxExDlg message handlers

BOOL CFTech_ListBoxExDlg::OnInitDialog()
{
		CDialogEx::OnInitDialog();

		ifstream is("test.txt");
		int tmpTryPara = 0;
		is >> tmpTryPara;
		interValTime = tmpTryPara;
		is >> tmpTryPara;
		tryMeasureTimes = tmpTryPara;
		float tmp;
		is >> tmp;
		stableRange = tmp;

		// Set the icon for this dialog.  The framework does this automatically
		//  when the application's main window is not a dialog
		SetIcon(m_hIcon, TRUE);			// Set big icon
		SetIcon(m_hIcon, FALSE);		// Set small icon

		BOOL ret = m_lbTest.InitControl(this);
		m_lbTest.SetAlignTextLM();
//		m_lbTest.SetColorBkg(255, 128, 128, 128);
//		m_lbTest.SetColorItemHot(255, 204, 99, 0);
//		m_lbTest.SetColorItemNomal(255, 128, 128, 128, 255, 64, 64, 64);
//		m_lbTest.SetColorTextHot(255, 0, 255, 0);
		//m_lbTest.AddString(L":      01    |    02      [0       20     ]  低阻仪");
		//m_lbTest.AddString(L":      03    |    04      [2.1k    2.2k   ]  M500表");
		//m_lbTest.AddString(L":      05    |    06      [999m    99999m ]  绝缘表");

		m_lbTest.SetCurSel(0);
		mWorkingName.SetWindowTextW(workingName);

		if(workingGroup == -1)
		{
			mWorkingGroup.SetWindowTextW(L"Forbidden");
			disableAllButton();
		}
		else if(workingGroup == 99)
		{
			mWorkingGroup.SetWindowTextW(L"Admin");
		}
		else
		{
			mWorkingGroup.SetWindowTextW(L"Tester");
			disableRootButton();
		}
		
		m_MCUDisConnectButton.EnableWindow(FALSE);
		m_MeterDisConnectButton.EnableWindow(FALSE);
		myUtil::getMcuComSets();
		myUtil::getMeterComSets();
		for (int i = 0; i <= 9; ++i)
		{
			TCHAR comName[32];
			wsprintf(comName, L"COM %d", i);
			mMCUComPort.InsertString(mMCUComPort.GetCount(), comName);
			mMeterComPort.InsertString(mMeterComPort.GetCount(), comName);
		}
		mMCUComPort.SetCurSel(myUtil::mcuCom);
		mMeterComPort.SetCurSel(myUtil::meterCom);

		//open uart com automaticly
		myUtil::getMeterComSets();
#ifdef debug_no_com
		myMeterSerial.Open(1, 115200);
#else
		// Open MCU Serial Port
		myMeterSerial.Open(myUtil::meterCom, myUtil::meterBaud);
#endif

		myUtil::getMcuComSets();
#ifdef debug_no_com
		myMeterSerial.Open(3, 115200);
#else
		// Open MCU Serial Port
		myMcuSerial.Open(myUtil::mcuCom, myUtil::mcuBaud);
#endif
		isMCUConnected = true;
		isMeterConnected = true;
		//start self test automaticly
		mEditCurProjectName.SetWindowTextW(L"自检");
		isSelfTesting = true;
		dlgShow.Create(IDD_DIALOG_selftesting, this);
		dlgShow.ShowWindow(SW_SHOW);
		dlgShow.CenterWindow();
		SetTimer(4, 100, NULL);
		//默认最大化
		ShowWindow(SW_MAXIMIZE);
		return TRUE;  // return TRUE  unless you set the focus to a control
}


void CFTech_ListBoxExDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialogEx::OnPaint();
	}
}

// The system calls this function to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CFTech_ListBoxExDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}


void CFTech_ListBoxExDlg::OnBnClickedCancel()
{
	loop = false;
	CDialogEx::OnCancel();
}

void CFTech_ListBoxExDlg::OnDestroy()
{
	CDialogEx::OnDestroy();

}

BOOL CFTech_ListBoxExDlg::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
	return CDialogEx::OnWndMsg(message, wParam, lParam, pResult);
}


// WindowProcedure MainLoop
void CFTech_ListBoxExDlg::MainLoop()
{
	while (loop)
	{

		MSG msg;
		if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
		{
			if (!GetMessage(&msg, NULL, 0, 0))
			{
				break;
			}
			::TranslateMessage(&msg);
			::DispatchMessage(&msg);
		}

		const int curT = timeGetTime();
		static int oldT = curT;
		const int elapseT = curT - oldT;
		const float t = elapseT * 0.001f;
		oldT = curT;
		//Process(t);
		Sleep(0);
	}
}

// Serial Transmitt/Receive Process
void CFTech_ListBoxExDlg::Process(float deltaT)
{
	if (isMCUConnected)
	{
		TCHAR data = 0;
		if (myMcuSerial.ReadData(&data, 1) > 0)
		{
			mcuResVec.push_back(data);
		}
	}
	if (isMeterConnected)
	{
		TCHAR data = 0;
		if (myMeterSerial.ReadData(&data, 1) > 0)
		{
			meterResString += data;
		}
	}
}

//function for double cliking the list item
void CFTech_ListBoxExDlg::OnClickedListBox()
{
	//get the select test item content
	CString text=L"";
	int pos = m_lbTest.GetCurSel();
	m_lbTest.GetText(pos,text);
	
	//get port and limit information from displaying text
	TestSeqEditor editDlg;
	editDlg.port1 = myUtil::getPort1(text);
	editDlg.port2 = myUtil::getPort2(text);
	string expectMax, expectMin,rangeMax, p1, p2;
	myUtil::parseToCmdStrPart(text, &p1, &p2, &expectMin, &expectMax,&rangeMax);
	editDlg.minlimit = CString(expectMin.c_str());
	editDlg.maxlimit = CString(expectMax.c_str());
	editDlg.rangeMax = CString(rangeMax.c_str());
	editDlg.maxlimit = CString(expectMax.c_str());
	editDlg.DoModal();
	CString newSeq = editDlg.setString;
	if (newSeq != "")
	{
		m_lbTest.DeleteString(pos);
		m_lbTest.InsertString(pos, editDlg.setString);
	}
}

void CFTech_ListBoxExDlg::OnBnClickedButton2()
{
}


void CFTech_ListBoxExDlg::OnBnClickedMCUPortConnect()
{
	if (isMCUConnected)
		return;
	//get config from file
	CString strComPort;
	mMCUComPort.GetWindowTextW(strComPort);
	myUtil::saveMcuComSets(strComPort);
	myUtil::getMcuComSets();

	myMcuSerial.Close();
	// Open MCU Serial Port
	if (myMcuSerial.Open(myUtil::mcuCom, myUtil::mcuBaud))
	//if (myMcuSerial.Open(6, 115200))
	{
		isMCUConnected = true;
		m_MCUConnectButton.EnableWindow(FALSE);
		m_MCUDisConnectButton.EnableWindow(TRUE);
	}
	else
	{
		AfxMessageBox(L"MCU Serial Port Connect Error!!");
	}
}


void CFTech_ListBoxExDlg::OnBnClickedButtonDisconMcu()
{
	if (isMCUConnected)
	{
		isMCUConnected = false;
		myMcuSerial.Close();
		m_MCUConnectButton.EnableWindow(TRUE);
		m_MCUDisConnectButton.EnableWindow(FALSE);
	}
}



/// <summary>
/// two kind of cmd
/// 1) is from list box ==> call display cmd format like ":   01 | 03     [200     210    ]  2K"
/// 2) used for detail excution ==> call raw cmd format like "P_1st:01 P_2st:03 电压"
/// use this funciont to trans display cmd to raw cmd
int CFTech_ListBoxExDlg::transRawCmd(CString cmd)
{
	McuUARTCmdManger mcuManager;
	int port1 = myUtil::getPort1(cmd);
	int port2 = myUtil::getPort2(cmd);
	if (ifRevertPort == 1)
	{
		int tmp = port1;
		port1 = port2;
		port2 = tmp;
	}

	CString tmp1, tmp2;
	tmp1.Format(L"%d", port1);
	tmp2.Format(L"%d", port2);
//	float maxVal = myUtil::getTestSelRangeMax(cmd);
//	if(maxVal>10 && maxVal<=10000001)
//	{
		//vdc and ad	 
		cmdVdc = mcuManager.port1KeyStr + tmp1 + mcuManager.cmdSplitChar
			+ mcuManager.port2KeyStr + tmp2 + mcuManager.cmdSplitChar + mcuManager.volKeyStr;
		cmdAdc = mcuManager.port1KeyStr + tmp1 + mcuManager.cmdSplitChar
			+ mcuManager.port2KeyStr + tmp2 + mcuManager.cmdSplitChar + mcuManager.curKeyStr;
//		return 2;
//	}
//	else
//	{
		cmdOhms= mcuManager.port1KeyStr + tmp1 + mcuManager.cmdSplitChar
			+ mcuManager.port2KeyStr + tmp2 + mcuManager.cmdSplitChar + mcuManager.resKeyStr;
//		return 1;
//	}
		return 0;
}

bool CFTech_ListBoxExDlg::tryExecuteOneMcuCmd(int tryCnt, CString cmd, bool isResetCmd)
{
	bool isExecutSuccess = false;
	McuUARTCmdManger mcuOper;
	mcuOper.updateCmdData(cmd);
	mcuOper.updateResetCmdData(cmd);
	for (int i = 0; i < tryCnt; i++)
	{
		if (isUserTerminal == true)
			return false;
		clearMcuSerialPort();
		mcuOper.executeOneCmd(&myMcuSerial, isResetCmd);//not reset cmd
		waitUntilGetMcuRes();
		CString logInfo = L"get response from mcu: ";
		for (int i = 0; i < mcuResVec.size(); i++)
		{
			CString tmp;
			tmp.Format(L" %x", mcuResVec[i]);
			logInfo += tmp;
		}
		myUtil::myLog(logInfo);

		if (-1 == mcuOper.parseResponse(mcuResVec, isResetCmd))
		{
			myUtil::myLog(L"mcu response error, try send once again");
			continue;
		}
		else
		{
			myUtil::myLog(L"mcu response success");
			isExecutSuccess = true;
			break;
		}
	}
	return isExecutSuccess;
}

void CFTech_ListBoxExDlg::clearMcuSerialPort()
{
	TCHAR data = 0;
	if (myMcuSerial.ReadData(&data, 1) > 0)
	{
		mcuResVec.push_back(data);
	}
	mcuResVec.clear();
}
void CFTech_ListBoxExDlg::waitUntilGetMcuRes()
{
	int cnt = 0;
	TCHAR data = 0;
	//wait until data appears in serial port
	while (myMcuSerial.ReadData(&data, 1) <= 0)
	{
		if (isUserTerminal == true)
			return;
		cnt++;
		if (cnt >= MCU_MAX_WAIT)
		{
			//time out
			myUtil::myLog(L"MCU response time out");
#ifndef debug_no_com
			isMcuComError = true;
#endif
			break;
		}
		Sleep(5);
	}
	//wait another 20ms for receive all data from serial port
	Sleep(20);
	mcuResVec.push_back(data);

	while (myMcuSerial.ReadData(&data, 1) > 0)
	{
		if (isUserTerminal == true)
			return;
		mcuResVec.push_back(data);
	}
}


void CFTech_ListBoxExDlg::clearMeterSerialPort()
{
	TCHAR data = 0;
	meterResString = "";
	meterResString += data;
	while (myMeterSerial.ReadData(&data, 1) > 0)
	{
		meterResString += data;
	}
	meterResString = "";
}
void CFTech_ListBoxExDlg::waitUntilGetMeterRes()
{
	int cnt = 0;
	TCHAR data = 0;
	//wait until data appears in serial port
	while (myMeterSerial.ReadData(&data, 1) <= 0)
	{
		if (isUserTerminal == true)
			return;
		cnt++;
		if (cnt >= METER_WAIT_MAX)
		{
			//time out
			myUtil::myLog(L"Meter response time out");
#ifndef debug_no_com
			isMeterComError = true;
#endif
			break;
		}
		Sleep(10);
	}
	//wait another 30ms for receive all data from serial port
	Sleep(20);
	meterResString += data;
	while (myMeterSerial.ReadData(&data, 1) > 0)
	{
		meterResString += data;
	}
}

float CFTech_ListBoxExDlg::readMeasureVal()
{
	MeterUARTCmdManger meterOper;
	clearMeterSerialPort();
	meterOper.readMeter(&myMeterSerial);
	waitUntilGetMeterRes();
	myUtil::myLog(L"get meter raw response:" + meterResString);
	float measureVal = myUtil::getFloatFromEStr(meterResString);
	CString floatStr;
	floatStr.Format(L"%s", myUtil::floatToStr(measureVal).c_str());
	myUtil::myLog(L"get measure float value:" + floatStr);
	return measureVal;
}
void CFTech_ListBoxExDlg::setMeterResMode()
{
	MeterUARTCmdManger meterOper;
	//get current test mode 
	clearMeterSerialPort();
	meterOper.executeOneCmd(&myMeterSerial, meterOper.queryTestMode);
	waitUntilGetMeterRes();
	Sleep(10);
	if (meterResString.Find(L"OHMS") != -1)
	{
		myUtil::myLog(L"It is OHMS test mode already");
	}
	else
	{
		clearMeterSerialPort();
		meterOper.executeOneCmd(&myMeterSerial, meterOper.testResCmd);
		waitUntilGetMeterRes();
		myUtil::myLog(L"set OHMS mode");
	}

}
void CFTech_ListBoxExDlg::setMeterVdcMode()
{
	MeterUARTCmdManger meterOper;
	//get current test mode 
	clearMeterSerialPort();
	meterOper.executeOneCmd(&myMeterSerial, meterOper.queryTestMode);
	waitUntilGetMeterRes();
	Sleep(10);
	if (meterResString.Find(L"VDC") != -1)
	{
		myUtil::myLog(L"it is VDC test mode already");
	}
	else
	{
		clearMeterSerialPort();
		meterOper.executeOneCmd(&myMeterSerial, meterOper.testVolCmd);
		waitUntilGetMeterRes();
		myUtil::myLog(L"set vdc test mode");
	}

}
void CFTech_ListBoxExDlg::setMeterAdcMode()
{
	MeterUARTCmdManger meterOper;
	//get current test mode 
	clearMeterSerialPort();
	meterOper.executeOneCmd(&myMeterSerial, meterOper.queryTestMode);
	waitUntilGetMeterRes();
	Sleep(10);
	if (meterResString.Find(L"ADC") != -1)
	{
		myUtil::myLog(L"it is adc test mode already");
	}
	else
	{
		clearMeterSerialPort();
		meterOper.executeOneCmd(&myMeterSerial, meterOper.testCurCmd);
		waitUntilGetMeterRes();
		myUtil::myLog(L"set adc test mode");
	}

}
void CFTech_ListBoxExDlg::setMeterRange(int range)
{
	MeterUARTCmdManger meterOper;
	//get current range
	clearMeterSerialPort();
	meterOper.executeOneCmd(&myMeterSerial, meterOper.queryRange);
	waitUntilGetMeterRes();
	Sleep(10);
	CString needRange;
	needRange.Format(L"%d", range);
	if (meterResString.Find(needRange) != -1)
	{
		myUtil::myLog(L"it is right test range already");
	}
	else
	{
		clearMeterSerialPort();
		meterOper.executeOneCmd(&myMeterSerial, meterOper.rangeCmd + L" " + needRange);
		waitUntilGetMeterRes();
		myUtil::myLog(L"set the need test range" + needRange);
	}

}
void CFTech_ListBoxExDlg::setRefreshRateOnce()
{
	clearMeterSerialPort();
	MeterUARTCmdManger meterOper;
	meterOper.prepareRefreshRate(&myMeterSerial);
	waitUntilGetMeterRes();
	myUtil::myLog(L"set refresh rate");
}



//onePortMeasure will ask mcu set switchs for the test ports, and use meter measure it.
float CFTech_ListBoxExDlg::onePortMeasure(CString cmd)
{
	bool tryRet = tryExecuteOneMcuCmd(3, cmd, false);
	if (!tryRet)
	{		
		myUtil::myLog(L"MCU test setting error");
		isComTryTimeOut = true;
		return 0.0;
		//AfxMessageBox(L"test fail at %d because mcu test",i);
	}
#ifdef debug_step_by_step
		AfxMessageBox(L"set cpu port already here");
#endif
	float testVal = keepMeasureUniStable(interValTime,tryMeasureTimes);
	CString floatStr;
	floatStr.Format(L"%s", myUtil::floatToStr(testVal).c_str());
#ifdef debug_step_by_step
		AfxMessageBox(L"get meter value" + floatStr);
#endif
	myUtil::myLog(L"reset mcu port setting");
	bool tryResetRet = tryExecuteOneMcuCmd(3, cmd, true);
	if (!tryResetRet)
	{
		isComTryTimeOut = true;
		return 0.0;
		myUtil::myLog(L"reset mcu port setting fail");
	}
	return testVal;
}

void CFTech_ListBoxExDlg::updateTestResultForCSV(string p1, string p2, string expectMin, 
	string expectMaxInput, string rangeMax, string valCString, string testResult, string rangeStr)
{

	string expectMax = expectMaxInput;
	if(expectMax == "99999M")
		expectMax = chi_wu_qiong_str;
	if (rangeStr == "10")
	{
		testResultVecForCsv_str.push_back((p1)+"," + (p2)+","
			+ (expectMin)+","+ (expectMax)+"," + "低阻档"+","
			+ (valCString) + "," + (testResult)
			+ "," +(rangeMax));
		testResultVecForCSV.push_back(CString(p1.c_str()) + L"," + CString(p2.c_str()) + L","
			+ CString(expectMin.c_str()) + L","
			+ CString(expectMax.c_str()) + L","
			+ L"低阻档" + L","
			+ CString(valCString.c_str()) + L","
			+ CString(testResult.c_str()) + L","
			+ CString(rangeMax.c_str()));
	}
	else if (rangeStr == "10M")
	{
		testResultVecForCsv_str.push_back((p1)+"," + (p2)+","
			+ (expectMin)+","
			+ (expectMax)+","
			+ "M500_1K档" +","
			+ (valCString) + "," + (testResult)
			+ "," + (rangeMax));
		testResultVecForCSV.push_back(CString(p1.c_str()) + L"," + CString(p2.c_str()) + L","
			+ CString(expectMin.c_str()) + L","
			+ CString(expectMax.c_str()) + L","
			+ L"M500_1K档" + L","
			+ CString(valCString.c_str()) + L","
			+ CString(testResult.c_str()) + L","
			+ CString(rangeMax.c_str()));
	}
	else if (rangeStr == "99999M")
	{
		testResultVecForCsv_str.push_back((p1)+"," + (p2)+","
			+ (expectMin)+","
			+ (expectMax)+","
			+ "兆欧档" +","
			+ (valCString) + "," + (testResult)
			+ "," + (rangeMax));
		testResultVecForCSV.push_back(CString(p1.c_str()) + L"," + CString(p2.c_str()) + L","
			+ CString(expectMin.c_str()) + L","
			+ CString(expectMax.c_str()) + L","
			+ L"兆欧档" + L","
			+ CString(valCString.c_str()) + L","
			+ CString(testResult.c_str()) + L","
			+ CString(rangeMax.c_str()));
	}
	else
	{
		testResultVecForCsv_str.push_back((p1)+"," + (p2)+","
			+ (expectMin)+","
			+ (expectMax)+","
			+ "M500_1K档" +","
			+ (valCString) + "," + (testResult)
			+ "," + (rangeMax));
		testResultVecForCSV.push_back(CString(p1.c_str()) + L"," + CString(p2.c_str()) + L","
			+ CString(expectMin.c_str()) + L","
			+ CString(expectMax.c_str()) + L","
			+ L"M500_1K档" + L","
			+ CString(valCString.c_str()) + L","
			+ CString(testResult.c_str()) + L","
			+ CString(rangeMax.c_str()));
	}
}

float CFTech_ListBoxExDlg::vadcTest(CString cmd, CString cmdVdc, CString cmdAdc)
{
	float val = 0.0;
	CString testFlag = L"fail";
	CString testResult = L"";
	CString rangeStr = myUtil::getTestSelRangeStr(cmd);
	setMeterVdcMode();
	float vdcVal = onePortMeasure(cmdVdc);
	setMeterAdcMode();
	float adcVal = onePortMeasure(cmdAdc);
	if ((adcVal > -0.000000001 && adcVal < 0.000000001) 
		&& (vdcVal > -0.000000001 && vdcVal < 0.000000001))
	{
		myUtil::myLog(L"abnormal because get 0 adc and vdc value");
		if (ifStopWhenError == 1)
		{
			isRequestToStop = true;
		}
		m_lbTest.seqTestFlagVec[m_lbTest.seqTestFlagVec.size()-1] = -1;
		val = -1.0;
		testFlag.Format(L" val=%s, fail", myUtil::floatToStr(val).c_str());
		testResult = (L"fail");
		if (ifStopWhenError == 1)
		{
			isRequestToStop = true;
		}
	}
	else
	{
		if ((vdcVal > 0.000000001 || vdcVal < -0.000000001) && (adcVal > -0.000000001 && adcVal < 0.000000001))
			val = 500000000.0;
		else
			val = vdcVal / adcVal;
		if (val < 0)
			val = -1.0 * val;
		if (val < 2.0)
			val = 0.0;
		CString debugStr;
		debugStr.Format(L"!!vdc adc calc %s = %s | %s", myUtil::floatToStr(val).c_str(), myUtil::floatToStr(vdcVal).c_str(), myUtil::floatToStr(adcVal).c_str());
		myUtil::myLog(debugStr);
		float downLimit = myUtil::getTestDownLimit(cmd);
		float upLimit = myUtil::getTestUpLimit(cmd);

		if (val >= downLimit && val <= upLimit + 0.1 && isComTryTimeOut == false)
		{
			testFlag.Format(L" val=%s, pass", myUtil::floatToStr(val).c_str());
			testResult = (L"合格");
			m_lbTest.seqTestFlagVec[m_lbTest.seqTestFlagVec.size()-1] = 1;
		}
		else
		{
			testFlag.Format(L" val=%s, fail", myUtil::floatToStr(val).c_str());
			testResult = (L"不合格");
			m_lbTest.seqTestFlagVec[m_lbTest.seqTestFlagVec.size()-1] = -1;
			if (ifStopWhenError == 1)
			{
				isRequestToStop = true;
			}
		}
	}

	testResultVec.push_back(cmd + testFlag);

	CString valCString;
	valCString.Format(L"%s", myUtil::floatToStr(val).c_str());
	string expectMax, expectMin,rangeMax, p1, p2;
	myUtil::parseToCmdStrPart(cmd, &p1, &p2, &expectMin, &expectMax, &rangeMax);
	//CString expectMaxRawStr = myUtil::getTestUpLimitStr(cmd);
	string valstr = CT2A(valCString.GetBuffer());
	string testResultStr = CT2A(testResult.GetBuffer());
	string rangStringStr = CT2A(rangeStr.GetBuffer());
	updateTestResultForCSV(p1, p2, expectMin, expectMax, 
		rangeMax, valstr, testResultStr, rangStringStr);
	return val;
}

float CFTech_ListBoxExDlg::ohmsRangeTest(CString rawCmd, int range, CString cmd)
{
	CString testFlag = L"fail";
	string testResult = "";
	setMeterResMode();
	setMeterRange(range);
	float val = onePortMeasure(cmd);
	float downLimit = myUtil::getTestDownLimit(rawCmd);
	float upLimit = myUtil::getTestUpLimit(rawCmd);
	CString rangeStr = myUtil::getTestSelRangeStr(rawCmd);
	if(val<2.0)
	{
		val = 0.0;
	}
	//make sure val larger than 0
	if(val >= downLimit && val <= upLimit+0.1 && isComTryTimeOut == false)
	{
		testFlag.Format(L" val=%s, pass",myUtil::floatToStr(val).c_str());
		testResult = "合格";
		myUtil::myLog(cmd + L"   test pass!!!");
		m_lbTest.seqTestFlagVec[m_lbTest.seqTestFlagVec.size()-1] = 1;
	}
	else
	{
		testFlag.Format(L" val=%s, fail",myUtil::floatToStr(val).c_str());
		testResult = "不合格";
		//todo terminal tests
		myUtil::myLog(cmd + L"   test fail!!!");
		m_lbTest.seqTestFlagVec[m_lbTest.seqTestFlagVec.size()-1] = -1;
		if (ifStopWhenError == 1)
		{
			isRequestToStop = true;
		}
	}

	testResultVec.push_back(cmd + testFlag);

	CString valCString;
	valCString.Format(L"%f",val);
	string expectMax, expectMin,rangeMax, p1, p2;
	myUtil::parseToCmdStrPart(rawCmd, &p1, &p2, &expectMin, &expectMax, &rangeMax);
	//CString expectMaxRawStr = myUtil::getTestSelRangeStr(rawCmd);
	string valstr = CT2A(valCString.GetBuffer());
	string testResultStr = testResult;
	string rangStringStr = CT2A(rangeStr.GetBuffer());
	updateTestResultForCSV(p1, p2, expectMin, expectMax,
		rangeMax, valstr, testResultStr, rangStringStr);
	return val;
	
}

void CFTech_ListBoxExDlg::disableRootButton()
{
	mAddSeqBtnCtl.EnableWindow(false);
	mDelSeqBtnCtl.EnableWindow(false);
	mEncryBtnCtl.EnableWindow(false);
	mDeEncryBtnCtl.EnableWindow(false);
	mOutputSeqBtnCtl.EnableWindow(false);
	mCreateDemoCsvBut.EnableWindow(false);
	mReverse.EnableWindow(false);
}

void CFTech_ListBoxExDlg::enableAllButton()
{
  mAddSeqBtnCtl.EnableWindow(true);
  mDelSeqBtnCtl.EnableWindow(true);
  mImportSeqBtnCtl.EnableWindow(true);
  mOutputSeqBtnCtl.EnableWindow(true);
  mExecuteSeqBtnCtl.EnableWindow(true);
  mBtnSelfTest.EnableWindow(true);
  mIfStopWhenError.EnableWindow(true);
  mReportBtn.EnableWindow(true);
  mClearSeqButCtl.EnableWindow(true);
  mShowMeasureButCtl.EnableWindow(true);
  mReverse.EnableWindow(true);
}
void CFTech_ListBoxExDlg::disableAllButton()
{
	mAddSeqBtnCtl.EnableWindow(false);
	mDelSeqBtnCtl.EnableWindow(false);
	mImportSeqBtnCtl.EnableWindow(false);
	mOutputSeqBtnCtl.EnableWindow(false);
	mExecuteSeqBtnCtl.EnableWindow(false);
	mBtnSelfTest.EnableWindow(false );
	mIfStopWhenError.EnableWindow(false);
	mReportBtn.EnableWindow(false);
	mClearSeqButCtl.EnableWindow(false);
	mShowMeasureButCtl.EnableWindow(false);
	mReverse.EnableWindow(false);
}

float startTestBaseRange(CFTech_ListBoxExDlg* dlg, CString cmdtmp, float downL, float upL, float selectRange)
{

	if ((selectRange > 10 && selectRange < 10000001)
		/* || (downL > 10 && downL < 10000001)
		|| (upL > 10 && upL < 10000001)*/)//max 200K
	{
		//use V/A approach
		return(dlg->vadcTest(cmdtmp, dlg->cmdVdc, dlg->cmdAdc));
	}
	else if (selectRange <= 10) //max 200
	{
		//range 1
		return(dlg->ohmsRangeTest(cmdtmp, 1, dlg->cmdOhms));
	}
	//else if (testUpLimit < 2000000)
	//{
	//	//range 5
	//	return(dlg->ohmsRangeTest(cmdtmp, 5, dlg->cmdOhms));
	//}
	//else if (selectRange <= 20000000)
	//{
	//	//range 6
	//	return(dlg->ohmsRangeTest(cmdtmp, 6, dlg->cmdOhms));
	//}
	else
	{
		//range 7
   		return(dlg->ohmsRangeTest(cmdtmp, 7, dlg->cmdOhms));
	}
}
void executeTask(CFTech_ListBoxExDlg *dlg)
{
	dlg->isUserTerminal = false;
	dlg->isComTryTimeOut = false;
	//reset mcu
	dlg->isMcuComError = false;
	dlg->isMeterComError = false;
	CString tmp = L"P_1st:00 P_2nd:00 ";
	tmp += chi_fuwei;
 	dlg->tryExecuteOneMcuCmd(3, tmp, false);
	//reset meter rate
	dlg->setRefreshRateOnce();
	int cmdCnt = dlg->m_lbTest.GetCount();
	for (int i = 0; i < cmdCnt; i++)
	{
		dlg->m_lbTest.SetCurSel(i);
		CString cmdtmp;
		dlg->m_lbTest.GetText(i, cmdtmp);
		myUtil::myLog(L"executing in execute task: " + cmdtmp);
		dlg->transRawCmd(cmdtmp);
		float testUpLimit = myUtil::getTestUpLimit(cmdtmp);
		float testDownLimit = myUtil::getTestDownLimit(cmdtmp);
		
		//update test status display
		CString updateSts;
		CString newStsWithTestVal;
		dlg->m_lbTest.GetText(i, updateSts);
		dlg->m_lbTest.DeleteString(i);

		CString ststmp = myUtil::completeStrLen(updateSts, CompleteLen);
		dlg->m_lbTest.InsertString(i, ststmp + L"测试中");
		dlg->m_lbTest.seqTestFlagVec.push_back(2);
		//test base user selected range
		float rangeMax = myUtil::getTestSelRangeMax(cmdtmp);
		float testVal =startTestBaseRange(dlg, cmdtmp, testDownLimit, testUpLimit,rangeMax);

		//update test result display
		//newStsWithTestVal.Format(L" %.1f", testVal);

		dlg->m_lbTest.DeleteString(i);
		string split33ValStr = myUtil::formatStr33Split(testVal);
		newStsWithTestVal = CString(split33ValStr.c_str());
		dlg->m_lbTest.InsertString(i, ststmp + newStsWithTestVal);

		dlg->mProcessPercent.SetPos((i + 1) * 100 / (cmdCnt));
		if(dlg->isUserTerminal == true)
		{
			AfxMessageBox(L"用户终止了当前测试!");
			dlg->mProcessPercent.SetPos(100);
			break;
		}
		
		if (dlg->isRequestToStop == true)
		{
			CString tmp;
			tmp.Format(L"%d", i);
			AfxMessageBox(L"Test error at " + tmp);
			dlg->mProcessPercent.SetPos(100);
			break;
		}
		if (dlg->isMcuComError == true)
		{
			AfxMessageBox(L"communication with mcu error");
			dlg->mProcessPercent.SetPos(100);
			break;
		}
		if (dlg->isMeterComError == true)
		{
			AfxMessageBox(L"communication with meter error");
			dlg->mProcessPercent.SetPos(100);
			break;
		}
	}
	//update the total test results
	bool isTotalPass = true;
	for (int i = 0; i < dlg->testResultVecForCsv_str.size(); i++)
	{
		string tmp = dlg->testResultVecForCsv_str[i];
		if (tmp.find("不合格") != string::npos)
		{
			isTotalPass = false;
			break;
		}
	}
	dlg->dlgShow.ShowWindow(false);
	if (isTotalPass)
	{
		dlg->mTestResult.SetWindowTextW(L"合格");
		if (dlg->isSelfTesting)
		{
			dlg->isSelfTesting = false;
			//AfxMessageBox(L"自检完成!");
		}
	}
	else
	{
		dlg->mTestResult.SetWindowTextW(L"不合格");
		if (dlg->isSelfTesting)
		{
			dlg->isSelfTesting = false;
			AfxMessageBox(L"自检失败,请检查设备,并重新开启软件!");
		}
	}
}

void CFTech_ListBoxExDlg::OnBnClickedButtenExecuteAll()
{
 //check if all coms are connected correctlly
	if (isMCUConnected != true || isMeterConnected != true)
	{
		AfxMessageBox(L"please make sure two serial ports connected");
		return;
	}
	//input SN dialog
	curSN = "";
	CInputSNDlg inputDlg;
	inputDlg.DoModal();
	curSN = inputDlg.mySN;
	mEditCurSN.SetWindowTextW(curSN);
	mTestResult.SetWindowTextW(L"待测试");
	if (curSN != "")
	{
		mProcessPercent.SetPos(0);
		disableAllButton();
		isRequestToStop = false;
		//refresh seq list immediately
		testResultVec.clear();
		testResultVecForCSV.clear();
		testResultVecForCsv_str.clear();
		m_lbTest.seqTestFlagVec.clear();
		ifStopWhenError = mIfStopWhenError.GetCheck();
		ifRevertPort = mReverse.GetCheck();

		int totalCnt = m_lbTest.GetCount();
		for (int i = 0; i < totalCnt; i++)
		{
			CString oldTableSeq;
			m_lbTest.GetText(i, oldTableSeq);
			m_lbTest.DeleteString(i);
			int pos = oldTableSeq.Find(L"档");
			if (pos == -1)
				pos = oldTableSeq.Find(L"表");
			CString recoverSeq;
			if (pos != -1)
				recoverSeq = oldTableSeq.Mid(0, pos +1);
			else
				recoverSeq = oldTableSeq;
			m_lbTest.InsertString(i, recoverSeq);
		}
		//m_lbTest.Invalidate(true);
		//m_lbTest.UpdateWindow();
		thread executeTh(executeTask, this);
		executeTh.detach();
		SetTimer(1, 100, NULL);
		SetTimer(2, 1000, NULL);
	}
	else 
	{
		AfxMessageBox(L"没有输入有效的SN,请重新开始测试.");
	}
}





void CFTech_ListBoxExDlg::OnBnClickedButtonConMeter()
{
	if (isMeterConnected)
		return;

	CString strComPort;
	mMeterComPort.GetWindowTextW(strComPort);
	myUtil::saveMeterComSets(strComPort);
	myUtil::getMeterComSets();

	// Open MCU Serial Port
	if (myMeterSerial.Open(myUtil::meterCom, myUtil::meterBaud))
	{
		isMeterConnected = true;
		m_MeterConnectButton.EnableWindow(FALSE);
		m_MeterDisConnectButton.EnableWindow(TRUE);
	}
	else
	{
		AfxMessageBox(L"Meter Serial Port Connect Error!!");
	}
}


void CFTech_ListBoxExDlg::OnBnClickedButtonDisconMeter()
{
	if (isMeterConnected)
	{
		isMeterConnected = false;
		myMeterSerial.Close();
		m_MeterConnectButton.EnableWindow(TRUE);
		m_MeterDisConnectButton.EnableWindow(FALSE);
	}
}

void CFTech_ListBoxExDlg::OnBnClickedBtnadd()
{
	gtest++;
	TestSeqEditor seqEditorDlg;
	seqEditorDlg.DoModal();

	CString tmp = seqEditorDlg.setString;
	if(tmp!="")
		m_lbTest.AddString(tmp);
}
void CFTech_ListBoxExDlg::OnBnClickedBtndelseq()
{
	int pos = m_lbTest.GetCurSel();
	m_lbTest.DeleteString(pos);
}


void CFTech_ListBoxExDlg::OnBnClickedButtonShowMeasure()
{
	if (isMeterConnected != true)
	{
		AfxMessageBox(L"check if meter is connected");
		return;
	}
	
	MeterUARTCmdManger meterOper;
	meterResString = "";
	meterOper.readMeter(&myMeterSerial);
	waitUntilGetMeterRes();
	mMeasureVal.SetWindowTextW(meterResString);
	
	/*
	McuUARTCmdManger mcuOper;
	CString cmd = L" | P_1st:04 | P_2nd:13 | ���ѹ |";
	mcuOper.updateCmdData(cmd);
	mcuOper.updateResetCmdData(cmd);

	mcuOper.executeOneCmd(&myMcuSerial, false);
	Sleep(100);
	mcuResVec.clear();
	TCHAR data;
	while (myMcuSerial.ReadData(&data, 1) > 0)
	{
		mcuResVec.push_back(data);
	}
	*/
}

void CFTech_ListBoxExDlg::inportToTable(CString strFilePath)
{
	wchar_t* old_locale = _wcsdup(_wsetlocale(LC_CTYPE, NULL));
	_wsetlocale(LC_CTYPE, _T("chs"));
	vector<CString> inportCmdVec;
	CStdioFile myFile;
	CString reverseFlag;
	if (myFile.Open(strFilePath, CFile::typeText | CFile::modeRead))
	{
		
		//first line for reverse flag
		myFile.ReadString(reverseFlag);
		CString lineStr;
		while (myFile.ReadString(lineStr))
		{
			string expectMax, expectMin, rangeMax, p1, p2;
			myUtil::parseToCmdStrPart(lineStr, &p1, &p2, &expectMin, &expectMax, &rangeMax);

			if (expectMax == "99999M")
			{
				CString inportCmd = Seq_Space + myUtil::formatSeqStrPortPart(CString(p1.c_str())) + Port1_Space
					+ myUtil::formatSeqStrPortPart(CString(p2.c_str())) + Port2_Space + myUtil::formatSeqStrMinMaxPart(CString(expectMin.c_str()))
					+ ExpMin_Space + L"∞     " 
					+ ExpMax_Space + myUtil::formatRangePart(CString(rangeMax.c_str()));
				inportCmdVec.push_back(inportCmd);
			}
			else
			{
				CString inportCmd = Seq_Space + myUtil::formatSeqStrPortPart(CString(p1.c_str())) + Port1_Space
					+ myUtil::formatSeqStrPortPart(CString(p2.c_str())) + Port2_Space + myUtil::formatSeqStrMinMaxPart(CString(expectMin.c_str()))
					+ ExpMin_Space + myUtil::formatSeqStrMinMaxPart(CString(expectMax.c_str()))
					+ ExpMax_Space + myUtil::formatRangePart(CString(rangeMax.c_str()));
				inportCmdVec.push_back(inportCmd);
			}
		}
	}
	myFile.Close();

	while (m_lbTest.GetCount())
		m_lbTest.DeleteString(0);
	for (int i = 0; i < inportCmdVec.size(); i++)
	{
		//todo check inport file
		m_lbTest.AddString(inportCmdVec[i]);
	}
	if (reverseFlag.Find(L":reverse")!=-1)
	{
		mReverse.SetCheck(1);
	}
	else
	{
		mReverse.SetCheck(0);
	}
	_wsetlocale(LC_CTYPE, old_locale);
	free(old_locale);
}
void CFTech_ListBoxExDlg::OnBnClickedBtnInportSeqs()
{
	CString tmpFile = myUtil::getCurPath() + L"products\\tmp.txt";
	const TCHAR pszFilter[] = _T("SEQ File (*.seq)|*.seq|Dynamic-link library (*.dll)|*.dll|Any Files (*.*)|*.*||");
	CFileDialog dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
		pszFilter, this);
	CString productPath = myUtil::getCurPath() + L"products";
	myUtil::createPath(productPath);
	dlg.m_ofn.lpstrInitialDir = productPath;
	CString strFilePath;
	if (dlg.DoModal() == IDOK)
	{
		strFilePath = dlg.GetPathName();
	}
	if (strFilePath == "")
	{
		AfxMessageBox(L"file path error");
		return;
	}
	//refresh seq list immediately
	testResultVec.clear();
	testResultVecForCSV.clear();
	testResultVecForCsv_str.clear();
	m_lbTest.seqTestFlagVec.clear();
	int pos = strFilePath.ReverseFind('\\');
	testSeqProjectName = strFilePath.Mid(pos + 1, strFilePath.GetLength() - pos - 5);
	myUtil::seqToTxt(strFilePath, tmpFile);
	inportToTable(tmpFile);
	mEditCurProjectName.SetWindowTextW(testSeqProjectName);
}


void CFTech_ListBoxExDlg::OnTimer(UINT_PTR nIDEvent)
{
	switch (nIDEvent)
	{
	case 1:
	  if(mProcessPercent.GetPos()==100)
	  {
	    KillTimer(1);
		CString workGroup;
		mWorkingGroup.GetWindowTextW(workGroup);		
	    enableAllButton();
		if (workGroup != L"Admin")
		{
			disableRootButton();
		}

	  }
		break;
	case 2:
		totalSecondCount++;
		if (totalSecondCount % (60 * 60) == 0)
		{
			//AfxMessageBox(L"it is 12 hours already");
		}
		break;
	case 3:
		KillTimer(3);
		CDialogEx::OnOK();
		break;
	case 4:
		KillTimer(4);
		OnBnClickedButtonSelfTest();
		break;
	default:
		break;
	}
	CDialogEx::OnTimer(nIDEvent);
}


void CFTech_ListBoxExDlg::OnBnClickedBtnoutputseq()
{
	CString tmpFile = myUtil::getCurPath() + L"products\\tmp.txt";
	const TCHAR pszFilter[] = _T("SEQ File (*.seq)|*.seq|Dynamic-link library (*.dll)|*.dll|Any Files (*.*)|*.*||");
	CFileDialog dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
		pszFilter, this);
	CString productPath = myUtil::getCurPath() + L"products";
	myUtil::createPath(productPath);
	dlg.m_ofn.lpstrInitialDir = productPath;
	CString strFilePath;
	if (dlg.DoModal() == IDOK)
	{
		strFilePath = dlg.GetPathName();
	}
	if (PathIsDirectory(strFilePath) || strFilePath == "")
	{
		AfxMessageBox(L"file path error, reselect please");
		return;
	}
	if (strFilePath.Find(L".seq") == -1)
	{
		strFilePath = strFilePath + L".seq";
	}


	int cmdCnt = m_lbTest.GetCount();
	testResultVec.clear();

	string strtmpFile = CT2A(tmpFile.GetBuffer());
	ofstream os(strtmpFile);
	CStdioFile myFile;
	int reverseSet = mReverse.GetCheck();
	if (1 == reverseSet)
	{
		os << ":reverse\n";
	}
	else
	{
		os << ":no_reverse\n";
	}

	for (int i = 0; i < cmdCnt; i++)
	{
		CString text = L"";
		m_lbTest.GetText(i, text);

		string expectMax, expectMin, rangeMax, p1, p2;
		myUtil::parseToCmdStrPart(text, &p1, &p2, &expectMin, &expectMax, &rangeMax);
		CString inportCmd = L"";
		if (expectMax == "99999M")
		{
			inportCmd = L": " + CString(p1.c_str()) + L" "
				+ CString(p2.c_str()) + L" " + myUtil::formatSeqStrMinMaxPart(CString(expectMin.c_str()))
				+ L" " + L"∞     " + L" " + myUtil::formatRangePart(CString(rangeMax.c_str()));
		}
		else
		{
			inportCmd = L": " + CString(p1.c_str()) + L" "
				+ CString(p2.c_str()) + L" " + myUtil::formatSeqStrMinMaxPart(CString(expectMin.c_str()))
				+ L" " + myUtil::formatSeqStrMinMaxPart(CString(expectMax.c_str())) + L" " + myUtil::formatRangePart(CString(rangeMax.c_str()));
		}
		inportCmd = inportCmd + L"\n";
		string strInportCmd = CT2A(inportCmd.GetBuffer());
		os << strInportCmd;
	}
	os.close();

	myUtil::txtToSeq(tmpFile, strFilePath);
}


void CFTech_ListBoxExDlg::OnBnClickedButtonReport()
{
	CString strFilePath = myUtil::SelectDirPath() + L"\\";
	CString rpName = L"";
	time_t timeSec = time(NULL);
	struct tm* ptm = localtime(&timeSec);
	CString curTime;
	curTime.Format(L"%04d%02d%02d%02d%02d%02d", ptm->tm_year+1900,ptm->tm_mon+1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
	CString testResult = L"";
	mTestResult.GetWindowTextW(testResult);
	rpName = testSeqProjectName + L"_" + curTime + L"_" + testResult;
	CString requestCsvPath = strFilePath + rpName + L".xlsx";
	CString requestPdfPath = strFilePath + rpName + L".pdf";

	CString csvPath = myUtil::getCurPath() + L"report.xlsx";
	CString pdfPath = myUtil::getCurPath() + L"report.pdf";
	string strcsvPath = CT2A(csvPath.GetBuffer());
	string strTestResult = CT2A(testResult.GetBuffer());
	string strTestSetId = CT2A(curTestSetId.GetBuffer());
	//check if the file exist
	ofstream os(strcsvPath);
	if (!os.is_open())
	{
		AfxMessageBox(L"report.xlsx file is occupied, please close it!");
		return;
	}
	os.close();
	DeleteFile(csvPath);

	string strDbPName = CT2A(testSeqProjectName.GetBuffer());
	string strTime = CT2A(curTime.GetBuffer());
	string strCurSn = CT2A(curSN.GetBuffer());
	string strWorkingName = CT2A(workingName.GetBuffer());
	string rec = "";
	CString csRec;
	rec += strDbPName + "阻抗测试记录表\n";
	csRec += testSeqProjectName + L"阻抗测试记录表\n";
	rec += "产品编号:\n";
	csRec += L"产品编号:\n";
	rec += strCurSn + "\n";
	csRec += curSN + L"\n";
	rec += "反向测试:\n";
	csRec += L"反向测试:\n";
	if (ifRevertPort == 1)
	{
		rec += "是\n";
		csRec += L"是\n";
	}
	else
	{
		rec += "否\n";
		csRec += L"否\n";
	}

	rec += "序号,正极,负极,最小值,最大值,测量方式,测量值,结论,\n";
	csRec += L"序号,正极,负极,最小值,最大值,测量方式,测量值,结论,\n";
	for (int i = 0; i < testResultVecForCSV.size(); i++)
	{
		CString text = L"";
		string textstr = "";
		text.Format(L"%d,", i + 1);
		textstr = CT2A(text.GetBuffer());
		text += testResultVecForCSV[i];
		textstr += testResultVecForCsv_str[i];
		text = text + L"\n";
		textstr += textstr + "\n";
		rec += textstr;
		csRec += text;
	}
	//收尾7行
	//空格一行
	rec += "    \n";
	csRec += L"    \n";
	//交付2行
	rec += "交付:\n";
	csRec += L"交付:\n";
	rec += strWorkingName + "\n";
	csRec += workingName + L"\n";
	//验收2行
	rec += "验收:\n";
	csRec += L"验收:\n";
	rec += "    \n";
	csRec += L"    \n";
	//日期2行
	rec += "日期:\n";
	csRec += L"日期:\n";
	rec += strTime + "\n";
	csRec += curTime + L"\n";

	//save test result into DB
	pRecordDB->addRecordToDB(strDbPName, strTime, strCurSn, strWorkingName, " ", strTestSetId,
		ifRevertPort==1?"是":"否", strTestResult, rec);
	//save test result into excel report.xlsx
	//test

	writeToExcel(csRec);
	CopyFile(csvPath,requestCsvPath,false);
	//conver excel file to pdf file
	myUtil::ConvertFile(csvPath, pdfPath);
	CopyFile(pdfPath,requestPdfPath,false);
	//open excel file
	ShellExecute(this->m_hWnd, L"open", requestCsvPath, NULL, NULL, SW_SHOW);
}

float CFTech_ListBoxExDlg::keepMeasureUniStable(int intervalT, int totalCnt)
{
  if(totalCnt <3)
	return 0.0;
  vector<float> valVec;
  int i = 0;
  for(i=0;i<totalCnt;i++)
  {
    float val = readMeasureVal();
    valVec.push_back(val);
    if(i>=3)
    {
      float delta1 = valVec[i]-valVec[i-1];
      float delta2 = valVec[i]-valVec[i-2];
      float delta3 = valVec[i-1]-valVec[i-2];
      if(fabs(delta1)<fabs(valVec[i-1]*stableRange) 
		&& fabs(delta2)<fabs(valVec[i-2]*stableRange)
	    && fabs(delta3)<fabs(valVec[i-2]*stableRange))
      {
		return(valVec[i]+valVec[i-1]+valVec[i-2])/3;
      }
    }
    Sleep(intervalT);
  }
  CString debugStr;
  debugStr.Format(L"debugxxx %d", i);
  myUtil::myLog(debugStr);
  return (valVec[i-1]+valVec[i-2]+valVec[i-3])/3;
}

void CFTech_ListBoxExDlg::OnBnClickedClearseqbutton()
{
	DoubleCheckToRmSeqs dlgDoubleCheck;
	dlgDoubleCheck.DoModal();
	if (dlgDoubleCheck.doubleChecked == true)
	{
		while (m_lbTest.GetCount())
			m_lbTest.DeleteString(0);
		//refresh seq list immediately
		testResultVec.clear();
		testResultVecForCSV.clear();
		testResultVecForCsv_str.clear();
		m_lbTest.seqTestFlagVec.clear();
	}
	else
	{
		//do nothing
	}
}

void CFTech_ListBoxExDlg::OnBnClickedButtonSelfTest()
{
	wchar_t* old_locale = _wcsdup(_wsetlocale(LC_CTYPE, NULL));
	_wsetlocale(LC_CTYPE, _T("chs"));

	//check if all coms are connected correctlly
	if (isMCUConnected != true || isMeterConnected != true)
	{
		AfxMessageBox(L"please check if mcu and meter are both connected");
		return;
	}
	mProcessPercent.SetPos(0);
	disableAllButton();
	inportToTable(L"self_test_seq.txt");
	isRequestToStop = false;
	//refresh seq list immediately
	testResultVec.clear();
	testResultVecForCSV.clear();
	testResultVecForCsv_str.clear();
	m_lbTest.seqTestFlagVec.clear();
	ifStopWhenError = mIfStopWhenError.GetCheck();
	isRequestToStop = false;
	thread executeTh(executeTask, this);
	executeTh.detach();
	SetTimer(1, 100, NULL);


}
void CFTech_ListBoxExDlg::OnBnClickedCheck2()
{
}


void CFTech_ListBoxExDlg::OnLbnSelchangeList1()
{
	
}

void CFTech_ListBoxExDlg::OnBnClickedButtonEncrip()
{  
	CString tmpFile = myUtil::getCurPath() + L"products\\tmp.txt";
	CString tiptmp = L"请选择编辑好的CSV文件。\n程序将自动转换为project目录下项目CSV文件。\n文件名称根据CSV中的项目名称自动定义";
	AfxMessageBox(tiptmp);
	const TCHAR pszFilter[] = _T("csv File (*.csv)|*.csv|Any Files (*.*)|*.*||");
	CFileDialog dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
		pszFilter, this);
	CString productPath = myUtil::getCurPath() + L"products";

	myUtil::createPath(productPath);
	dlg.m_ofn.lpstrInitialDir = productPath;
	CString strFilePath;
	if (dlg.DoModal() == IDOK)
	{
		strFilePath = dlg.GetPathName();
	}
	if (strFilePath == "")
	{
		AfxMessageBox(L"file path error");
		return;
	}
	CString projectName = myUtil::csvToTxt(strFilePath, tmpFile);
	CString seqFile = productPath + L"\\" + projectName + L".seq";
	myUtil::txtToSeq(tmpFile, seqFile);
}


void CFTech_ListBoxExDlg::OnBnClickedButtonDeencry()
{
	CString tmpFile = myUtil::getCurPath() + L"products\\tmp.txt";
	CString tiptmp = L"请选择项目SEQ文件。\n程序将自动转换为同目录下同名CSV文件。";
	AfxMessageBox(tiptmp);
	const TCHAR pszFilter[] = _T("seq File (*.seq)|*.seq|Any Files (*.*)|*.*||");
	CFileDialog dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
		pszFilter, this);
	CString productPath = myUtil::getCurPath() + L"products";

	myUtil::createPath(productPath);
	dlg.m_ofn.lpstrInitialDir = productPath;
	CString strFilePath;
	if (dlg.DoModal() == IDOK)
	{
		strFilePath = dlg.GetPathName();
	}
	if (strFilePath == "")
	{
		AfxMessageBox(L"file path error");
		return;
	}
	
	myUtil::seqToTxt(strFilePath, tmpFile);
	CString projectName = strFilePath;
	int pos = projectName.ReverseFind('\\');
	CString realProjectName = projectName.Mid(pos + 1, projectName.GetLength() - pos - 5);

	CString csvFile = myUtil::getCurPath() + L"products\\" + realProjectName + L".csv";
	myUtil::txtToCsv(tmpFile, csvFile, realProjectName);
}

#if 0
void CFTech_ListBoxExDlg::OnBnClickedButtonReport()
{
	//test
	testExcel();

	CString mdPath = myUtil::getCurPath() + L"report.md";
	CString csvPath = myUtil::getCurPath() + L"report.csv";
	CString pdfPath = myUtil::getCurPath() + L"report.pdf";
	FILE* fstream;
	_tfopen_s(&fstream, mdPath, L"w+,ccs=UTF-8");
	CStdioFile myFile(fstream);
	myFile.WriteString(L"# test report\n");
	myFile.WriteString(L"## test project\n");
	myFile.WriteString(L"1.tester XXX");
	time_t timeSec = time(NULL);
	struct tm* ptm = localtime(&timeSec);
	CString curTime;
	curTime.Format(L"%02d-%02d %02d:%02d:%02d : \n", ptm->tm_mon, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
	myFile.WriteString(L"2. test time" + curTime);
	myFile.WriteString(L"\n## detail test result\n");

	for (int i = 0; i < testResultVec.size(); i++)
	{
		CString text = L"";
		text.Format(L"%d.", i + 1);
		text += testResultVec[i];
		text = text + L"\n";
		myFile.WriteString(text);
	}
	myFile.Close();

	FILE* fstreamCsv;
	_tfopen_s(&fstreamCsv, csvPath, L"w+,ccs=UTF-8");
	if (fstreamCsv == NULL)
	{
		AfxMessageBox(L"file is occupied");
		return;
	}
	CStdioFile myFileCsv(fstreamCsv);
	string strDbPName = CT2A(testSeqProjectName.GetBuffer());
	string strTime = CT2A(curTime.GetBuffer());
	string rec = "";
	myFileCsv.WriteString(L"test report\n");
	rec += "test report\n";
	myFileCsv.WriteString(L"test project\n");
	rec += "test project\n";
	myFileCsv.WriteString(L"1. testXXX\n");
	rec += "1. testXXX\n";
	myFileCsv.WriteString(L"2. test time" + curTime);
	rec += "2. test time" + strTime;
	myFileCsv.WriteString(L"\ndetail report\n");
	rec += "\ndetail report\n";
	myFileCsv.WriteString(L"seq,port1,port2,expectMin,expectMax,range,test result\n");
	rec += "seq,port1,port2,expectMin,expectMax,range,test result\n";
	for (int i = 0; i < testResultVecForCSV.size(); i++)
	{
		CString text = L"";
		text.Format(L"%d,", i + 1);
		text += testResultVecForCSV[i];
		text = text + L"\n";
		myFileCsv.WriteString(text);
		rec += CT2A(text.GetBuffer());
	}
	myFileCsv.Close();

	//save test result into DB
	pRecordDB->addRecordToDB(strDbPName, strTime, rec);
	//ShellExecute(this->m_hWnd, L"open", L"pandoc.exe", L" report.md -o report.docx", NULL, SW_HIDE);
	myUtil::ConvertFile(csvPath, pdfPath);

	//open excel file
	ShellExecute(this->m_hWnd, L"open", csvPath, NULL, NULL, SW_SHOW);
}
#endif



void CFTech_ListBoxExDlg::OnBnClickedButCreateCsvDemo()
{
	CString csvFile = myUtil::getCurPath() + L"products\\demo.csv";
	string csvFileStr = CT2A(csvFile.GetBuffer());
	// TODO: 在此添加控件通知处理程序代码
	ofstream os(csvFileStr);
	if (!os.is_open())
	{
		AfxMessageBox(L"csv模板文件demo.csv被占用\n ");
		return;
	}
	string lineStr;
	lineStr = "#项目名称,,,demo,\n";
	os << lineStr;
	os << "#反向标志(选项支持是/否),,,否\n";
	os << "####,#正极,#负极,#期望下限,#期望上限,#测量方式,,无穷大请使用∞    注意带#的是关键字段不可缺失和更改\n";
	os << "#:,1,2,0,1,低阻档,\n";
	os << "#:,3,4,3.1k, 6k,M500_1K档, \n";
	os << "#:,5,6,20k,∞,兆欧档, \n";
	os.close();
	AfxMessageBox(L"csv模板已经生成,具体路径如下\n " + csvFile);
}


void CFTech_ListBoxExDlg::OnBnClickedUserterminate()
{
	isUserTerminal = true;
	// TODO: 在此添加控件通知处理程序代码
}
